/*************************************************************************
 *          ITLONG CAPITAL CONFIDENTIAL AND PROPRIETARY
 *
 *          COPYRIGHT (C) ITLONG CAPITAL CORPORATION 2017
 *    ALL RIGHTS RESERVED BY ITLONG CAPITAL CORPORATION. THIS PROGRAM
 * MUST BE USED SOLELY FOR THE PURPOSE FOR WHICH IT WAS FURNISHED BY
 * ITLONG CAPITAL CORPORATION. NO PART OF THIS PROGRAM MAY BE REPRODUCED
 * OR DISCLOSED TO OTHERS, IN ANY FORM, WITHOUT THE PRIOR WRITTEN
 * PERMISSION OF ITLONG CAPITAL CORPORATION. USE OF COPYRIGHT NOTICE
 * DOES NOT EVIDENCE PUBLICATION OF THE PROGRAM.
 *          ITLONG CAPITAL CONFIDENTIAL AND PROPRIETARY
 *************************************************************************/

package com.itlong.cloud.thrown;

import com.alibaba.fastjson.JSONObject;
import com.itlong.cloud.constants.RabbitMQConstant;
import com.itlong.cloud.rabbitmq.config.MessageSender;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;

/**
 * <desc>
 *      扩展{@link RuntimeException}提供数据层例外。
 *</desc>
 *
 * @createDate 2017/09/14
 */
@Component
public class DataAccessException extends RuntimeException {

    static final long serialVersionUID = -3425000197900000033L;

    protected static final Logger LOG = LoggerFactory.getLogger(DataAccessException.class);

    @Autowired
    private MessageSender messageSender;

    private static  MessageSender  messageSenderCls;


    protected Boolean forPage = true;

    @PostConstruct
    public  void  init(){
        //利用容器启动注入的messageSender赋值给类成员messageSenderCls
        messageSenderCls  =  this.messageSender;
    }


    public DataAccessException() {
        super();
    }

    public DataAccessException(Boolean forPage) {
        super();
        this.forPage = forPage;
    }

    public DataAccessException(String message) {
        super(message);
    }

    public DataAccessException(String message, Boolean forPage) {
        super(message);
        this.forPage = forPage;
    }

    public DataAccessException(String message, Throwable cause) {
        super(message, cause);
        LOG.error(message,cause);
        boolean isSelfClass = subCauseIsSelfCls(cause);
        if(!isSelfClass){
            //发短信通知还有台开发人员
            notifyDevelopers(message);

        }
    }

    public DataAccessException(String message, Throwable cause, Boolean forPage) {
        super(message, cause);
        this.forPage = forPage;
    }

    public DataAccessException(Throwable cause) {
        super(cause);
    }

    public DataAccessException(Throwable cause, Boolean forPage) {
        super(cause);
        this.forPage = forPage;
    }

    public Boolean forPage() {
        return this.forPage;
    }

    /**
     * <desc>
     *      被捕获的异常链中是否包含DataAccessException
     * </desc>
     *
     * @param Throwable e  异常
     * @return
     * @author pengwei
     * @createDate 2020/11/16
     */
    private  boolean  subCauseIsSelfCls(Throwable e){
        if(e==null){
            return false;
        }
        boolean isSelfClass = e  instanceof  DataAccessException;
        if(isSelfClass){
            return  true;
        }else{
            return subCauseIsSelfCls(e.getCause());
        }
    }

    /**
     * <desc>
     *       短信通知开发人员错误的日志
     *       1小时之内只能发送3次短信
     * </desc>
     *
     * @param msg 错误信息
     * @author pengwei
     * @createDate 2020/11/16
     */
    private   synchronized  void   notifyDevelopers(String  msg){
        try {
            Map<String,Object> params = new HashMap<>();
            params.put("msg",msg);
            JSONObject obj = new JSONObject();
            obj.put("data",params);
            messageSenderCls.send(RabbitMQConstant.RABBITMQ_NOTIFY_DEVLOPS_EXCPTMSG_QUEUE,
                    obj.toJSONString(),RabbitMQConstant.RABBITMQ_NOTIFY_DEVLOPS_EXCPTMSG_EXCHANGE,
                    RabbitMQConstant.RABBITMQ_NOTIFY_DEVLOPS_EXCPTMSG_KEY);
        } catch (Exception e) {
            LOG.error("【短信通知开发人员错误的日志】失败",e);
        }
    }
}
